// File generated from our OpenAPI spec
package com.stripe.param;

import com.google.gson.annotations.SerializedName;
import com.stripe.net.ApiRequestParams;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.EqualsAndHashCode;
import lombok.Getter;

@Getter
@EqualsAndHashCode(callSuper = false)
public class ProductCreateParams extends ApiRequestParams {
  /** Whether the product is currently available for purchase. Defaults to {@code true}. */
  @SerializedName("active")
  Boolean active;

  /**
   * Data used to generate a new <a href="https://stripe.com/docs/api/prices">Price</a> object. This
   * Price will be set as the default price for this product.
   */
  @SerializedName("default_price_data")
  DefaultPriceData defaultPriceData;

  /**
   * The product's description, meant to be displayable to the customer. Use this field to
   * optionally store a long form explanation of the product being sold for your own rendering
   * purposes.
   */
  @SerializedName("description")
  String description;

  /** Specifies which fields in the response should be expanded. */
  @SerializedName("expand")
  List<String> expand;

  /**
   * Map of extra parameters for custom features not available in this client library. The content
   * in this map is not serialized under this field's {@code @SerializedName} value. Instead, each
   * key/value pair is serialized as if the key is a root-level field (serialized) name in this
   * param object. Effectively, this map is flattened to its parent instance.
   */
  @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
  Map<String, Object> extraParams;

  /**
   * An identifier will be randomly generated by Stripe. You can optionally override this ID, but
   * the ID must be unique across all products in your Stripe account.
   */
  @SerializedName("id")
  String id;

  /** A list of up to 8 URLs of images for this product, meant to be displayable to the customer. */
  @SerializedName("images")
  List<String> images;

  /**
   * A list of up to 15 marketing features for this product. These are displayed in <a
   * href="https://stripe.com/docs/payments/checkout/pricing-table">pricing tables</a>.
   */
  @SerializedName("marketing_features")
  List<ProductCreateParams.MarketingFeature> marketingFeatures;

  /**
   * Set of <a href="https://stripe.com/docs/api/metadata">key-value pairs</a> that you can attach
   * to an object. This can be useful for storing additional information about the object in a
   * structured format. Individual keys can be unset by posting an empty value to them. All keys can
   * be unset by posting an empty value to {@code metadata}.
   */
  @SerializedName("metadata")
  Map<String, String> metadata;

  /** <strong>Required.</strong> The product's name, meant to be displayable to the customer. */
  @SerializedName("name")
  String name;

  /** The dimensions of this product for shipping purposes. */
  @SerializedName("package_dimensions")
  PackageDimensions packageDimensions;

  /** Whether this product is shipped (i.e., physical goods). */
  @SerializedName("shippable")
  Boolean shippable;

  /**
   * An arbitrary string to be displayed on your customer's credit card or bank statement. While
   * most banks display this information consistently, some may display it incorrectly or not at
   * all.
   *
   * <p>This may be up to 22 characters. The statement description may not include {@code <}, {@code
   * >}, {@code \}, {@code "}, {@code '} characters, and will appear on your customer's statement in
   * capital letters. Non-ASCII characters are automatically stripped. It must contain at least one
   * letter. Only used for subscription payments.
   */
  @SerializedName("statement_descriptor")
  String statementDescriptor;

  /** A <a href="https://stripe.com/docs/tax/tax-categories">tax code</a> ID. */
  @SerializedName("tax_code")
  String taxCode;

  /**
   * The type of the product. Defaults to {@code service} if not explicitly specified, enabling use
   * of this product with Subscriptions and Plans. Set this parameter to {@code good} to use this
   * product with Orders and SKUs. On API versions before {@code 2018-02-05}, this field defaults to
   * {@code good} for compatibility reasons.
   */
  @SerializedName("type")
  Type type;

  /**
   * A label that represents units of this product. When set, this will be included in customers'
   * receipts, invoices, Checkout, and the customer portal.
   */
  @SerializedName("unit_label")
  String unitLabel;

  /** A URL of a publicly-accessible webpage for this product. */
  @SerializedName("url")
  String url;

  private ProductCreateParams(
      Boolean active,
      DefaultPriceData defaultPriceData,
      String description,
      List<String> expand,
      Map<String, Object> extraParams,
      String id,
      List<String> images,
      List<ProductCreateParams.MarketingFeature> marketingFeatures,
      Map<String, String> metadata,
      String name,
      PackageDimensions packageDimensions,
      Boolean shippable,
      String statementDescriptor,
      String taxCode,
      Type type,
      String unitLabel,
      String url) {
    this.active = active;
    this.defaultPriceData = defaultPriceData;
    this.description = description;
    this.expand = expand;
    this.extraParams = extraParams;
    this.id = id;
    this.images = images;
    this.marketingFeatures = marketingFeatures;
    this.metadata = metadata;
    this.name = name;
    this.packageDimensions = packageDimensions;
    this.shippable = shippable;
    this.statementDescriptor = statementDescriptor;
    this.taxCode = taxCode;
    this.type = type;
    this.unitLabel = unitLabel;
    this.url = url;
  }

  public static Builder builder() {
    return new Builder();
  }

  public static class Builder {
    private Boolean active;

    private DefaultPriceData defaultPriceData;

    private String description;

    private List<String> expand;

    private Map<String, Object> extraParams;

    private String id;

    private List<String> images;

    private List<ProductCreateParams.MarketingFeature> marketingFeatures;

    private Map<String, String> metadata;

    private String name;

    private PackageDimensions packageDimensions;

    private Boolean shippable;

    private String statementDescriptor;

    private String taxCode;

    private Type type;

    private String unitLabel;

    private String url;

    /** Finalize and obtain parameter instance from this builder. */
    public ProductCreateParams build() {
      return new ProductCreateParams(
          this.active,
          this.defaultPriceData,
          this.description,
          this.expand,
          this.extraParams,
          this.id,
          this.images,
          this.marketingFeatures,
          this.metadata,
          this.name,
          this.packageDimensions,
          this.shippable,
          this.statementDescriptor,
          this.taxCode,
          this.type,
          this.unitLabel,
          this.url);
    }

    /** Whether the product is currently available for purchase. Defaults to {@code true}. */
    public Builder setActive(Boolean active) {
      this.active = active;
      return this;
    }

    /**
     * Data used to generate a new <a href="https://stripe.com/docs/api/prices">Price</a> object.
     * This Price will be set as the default price for this product.
     */
    public Builder setDefaultPriceData(ProductCreateParams.DefaultPriceData defaultPriceData) {
      this.defaultPriceData = defaultPriceData;
      return this;
    }

    /**
     * The product's description, meant to be displayable to the customer. Use this field to
     * optionally store a long form explanation of the product being sold for your own rendering
     * purposes.
     */
    public Builder setDescription(String description) {
      this.description = description;
      return this;
    }

    /**
     * Add an element to `expand` list. A list is initialized for the first `add/addAll` call, and
     * subsequent calls adds additional elements to the original list. See {@link
     * ProductCreateParams#expand} for the field documentation.
     */
    public Builder addExpand(String element) {
      if (this.expand == null) {
        this.expand = new ArrayList<>();
      }
      this.expand.add(element);
      return this;
    }

    /**
     * Add all elements to `expand` list. A list is initialized for the first `add/addAll` call, and
     * subsequent calls adds additional elements to the original list. See {@link
     * ProductCreateParams#expand} for the field documentation.
     */
    public Builder addAllExpand(List<String> elements) {
      if (this.expand == null) {
        this.expand = new ArrayList<>();
      }
      this.expand.addAll(elements);
      return this;
    }

    /**
     * Add a key/value pair to `extraParams` map. A map is initialized for the first `put/putAll`
     * call, and subsequent calls add additional key/value pairs to the original map. See {@link
     * ProductCreateParams#extraParams} for the field documentation.
     */
    public Builder putExtraParam(String key, Object value) {
      if (this.extraParams == null) {
        this.extraParams = new HashMap<>();
      }
      this.extraParams.put(key, value);
      return this;
    }

    /**
     * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
     * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
     * See {@link ProductCreateParams#extraParams} for the field documentation.
     */
    public Builder putAllExtraParam(Map<String, Object> map) {
      if (this.extraParams == null) {
        this.extraParams = new HashMap<>();
      }
      this.extraParams.putAll(map);
      return this;
    }

    /**
     * An identifier will be randomly generated by Stripe. You can optionally override this ID, but
     * the ID must be unique across all products in your Stripe account.
     */
    public Builder setId(String id) {
      this.id = id;
      return this;
    }

    /**
     * Add an element to `images` list. A list is initialized for the first `add/addAll` call, and
     * subsequent calls adds additional elements to the original list. See {@link
     * ProductCreateParams#images} for the field documentation.
     */
    public Builder addImage(String element) {
      if (this.images == null) {
        this.images = new ArrayList<>();
      }
      this.images.add(element);
      return this;
    }

    /**
     * Add all elements to `images` list. A list is initialized for the first `add/addAll` call, and
     * subsequent calls adds additional elements to the original list. See {@link
     * ProductCreateParams#images} for the field documentation.
     */
    public Builder addAllImage(List<String> elements) {
      if (this.images == null) {
        this.images = new ArrayList<>();
      }
      this.images.addAll(elements);
      return this;
    }

    /**
     * Add an element to `marketingFeatures` list. A list is initialized for the first `add/addAll`
     * call, and subsequent calls adds additional elements to the original list. See {@link
     * ProductCreateParams#marketingFeatures} for the field documentation.
     */
    public Builder addMarketingFeature(ProductCreateParams.MarketingFeature element) {
      if (this.marketingFeatures == null) {
        this.marketingFeatures = new ArrayList<>();
      }
      this.marketingFeatures.add(element);
      return this;
    }

    /**
     * Add all elements to `marketingFeatures` list. A list is initialized for the first
     * `add/addAll` call, and subsequent calls adds additional elements to the original list. See
     * {@link ProductCreateParams#marketingFeatures} for the field documentation.
     */
    public Builder addAllMarketingFeature(List<ProductCreateParams.MarketingFeature> elements) {
      if (this.marketingFeatures == null) {
        this.marketingFeatures = new ArrayList<>();
      }
      this.marketingFeatures.addAll(elements);
      return this;
    }

    /**
     * Add a key/value pair to `metadata` map. A map is initialized for the first `put/putAll` call,
     * and subsequent calls add additional key/value pairs to the original map. See {@link
     * ProductCreateParams#metadata} for the field documentation.
     */
    public Builder putMetadata(String key, String value) {
      if (this.metadata == null) {
        this.metadata = new HashMap<>();
      }
      this.metadata.put(key, value);
      return this;
    }

    /**
     * Add all map key/value pairs to `metadata` map. A map is initialized for the first
     * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
     * See {@link ProductCreateParams#metadata} for the field documentation.
     */
    public Builder putAllMetadata(Map<String, String> map) {
      if (this.metadata == null) {
        this.metadata = new HashMap<>();
      }
      this.metadata.putAll(map);
      return this;
    }

    /** <strong>Required.</strong> The product's name, meant to be displayable to the customer. */
    public Builder setName(String name) {
      this.name = name;
      return this;
    }

    /** The dimensions of this product for shipping purposes. */
    public Builder setPackageDimensions(ProductCreateParams.PackageDimensions packageDimensions) {
      this.packageDimensions = packageDimensions;
      return this;
    }

    /** Whether this product is shipped (i.e., physical goods). */
    public Builder setShippable(Boolean shippable) {
      this.shippable = shippable;
      return this;
    }

    /**
     * An arbitrary string to be displayed on your customer's credit card or bank statement. While
     * most banks display this information consistently, some may display it incorrectly or not at
     * all.
     *
     * <p>This may be up to 22 characters. The statement description may not include {@code <},
     * {@code >}, {@code \}, {@code "}, {@code '} characters, and will appear on your customer's
     * statement in capital letters. Non-ASCII characters are automatically stripped. It must
     * contain at least one letter. Only used for subscription payments.
     */
    public Builder setStatementDescriptor(String statementDescriptor) {
      this.statementDescriptor = statementDescriptor;
      return this;
    }

    /** A <a href="https://stripe.com/docs/tax/tax-categories">tax code</a> ID. */
    public Builder setTaxCode(String taxCode) {
      this.taxCode = taxCode;
      return this;
    }

    /**
     * The type of the product. Defaults to {@code service} if not explicitly specified, enabling
     * use of this product with Subscriptions and Plans. Set this parameter to {@code good} to use
     * this product with Orders and SKUs. On API versions before {@code 2018-02-05}, this field
     * defaults to {@code good} for compatibility reasons.
     */
    public Builder setType(ProductCreateParams.Type type) {
      this.type = type;
      return this;
    }

    /**
     * A label that represents units of this product. When set, this will be included in customers'
     * receipts, invoices, Checkout, and the customer portal.
     */
    public Builder setUnitLabel(String unitLabel) {
      this.unitLabel = unitLabel;
      return this;
    }

    /** A URL of a publicly-accessible webpage for this product. */
    public Builder setUrl(String url) {
      this.url = url;
      return this;
    }
  }

  @Getter
  @EqualsAndHashCode(callSuper = false)
  public static class DefaultPriceData {
    /**
     * <strong>Required.</strong> Three-letter <a
     * href="https://www.iso.org/iso-4217-currency-codes.html">ISO currency code</a>, in lowercase.
     * Must be a <a href="https://stripe.com/docs/currencies">supported currency</a>.
     */
    @SerializedName("currency")
    String currency;

    /**
     * Prices defined in each available currency option. Each key must be a three-letter <a
     * href="https://www.iso.org/iso-4217-currency-codes.html">ISO currency code</a> and a <a
     * href="https://stripe.com/docs/currencies">supported currency</a>.
     */
    @SerializedName("currency_options")
    Map<String, ProductCreateParams.DefaultPriceData.CurrencyOption> currencyOptions;

    /**
     * When set, provides configuration for the amount to be adjusted by the customer during
     * Checkout Sessions and Payment Links.
     */
    @SerializedName("custom_unit_amount")
    CustomUnitAmount customUnitAmount;

    /**
     * Map of extra parameters for custom features not available in this client library. The content
     * in this map is not serialized under this field's {@code @SerializedName} value. Instead, each
     * key/value pair is serialized as if the key is a root-level field (serialized) name in this
     * param object. Effectively, this map is flattened to its parent instance.
     */
    @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
    Map<String, Object> extraParams;

    /**
     * Set of <a href="https://stripe.com/docs/api/metadata">key-value pairs</a> that you can attach
     * to an object. This can be useful for storing additional information about the object in a
     * structured format. Individual keys can be unset by posting an empty value to them. All keys
     * can be unset by posting an empty value to {@code metadata}.
     */
    @SerializedName("metadata")
    Map<String, String> metadata;

    /** The recurring components of a price such as {@code interval} and {@code interval_count}. */
    @SerializedName("recurring")
    Recurring recurring;

    /**
     * Only required if a <a
     * href="https://stripe.com/docs/tax/products-prices-tax-categories-tax-behavior#setting-a-default-tax-behavior-(recommended)">default
     * tax behavior</a> was not provided in the Stripe Tax settings. Specifies whether the price is
     * considered inclusive of taxes or exclusive of taxes. One of {@code inclusive}, {@code
     * exclusive}, or {@code unspecified}. Once specified as either {@code inclusive} or {@code
     * exclusive}, it cannot be changed.
     */
    @SerializedName("tax_behavior")
    TaxBehavior taxBehavior;

    /**
     * A positive integer in cents (or local equivalent) (or 0 for a free price) representing how
     * much to charge. One of {@code unit_amount}, {@code unit_amount_decimal}, or {@code
     * custom_unit_amount} is required.
     */
    @SerializedName("unit_amount")
    Long unitAmount;

    /**
     * Same as {@code unit_amount}, but accepts a decimal value in cents (or local equivalent) with
     * at most 12 decimal places. Only one of {@code unit_amount} and {@code unit_amount_decimal}
     * can be set.
     */
    @SerializedName("unit_amount_decimal")
    BigDecimal unitAmountDecimal;

    private DefaultPriceData(
        String currency,
        Map<String, ProductCreateParams.DefaultPriceData.CurrencyOption> currencyOptions,
        CustomUnitAmount customUnitAmount,
        Map<String, Object> extraParams,
        Map<String, String> metadata,
        Recurring recurring,
        TaxBehavior taxBehavior,
        Long unitAmount,
        BigDecimal unitAmountDecimal) {
      this.currency = currency;
      this.currencyOptions = currencyOptions;
      this.customUnitAmount = customUnitAmount;
      this.extraParams = extraParams;
      this.metadata = metadata;
      this.recurring = recurring;
      this.taxBehavior = taxBehavior;
      this.unitAmount = unitAmount;
      this.unitAmountDecimal = unitAmountDecimal;
    }

    public static Builder builder() {
      return new Builder();
    }

    public static class Builder {
      private String currency;

      private Map<String, ProductCreateParams.DefaultPriceData.CurrencyOption> currencyOptions;

      private CustomUnitAmount customUnitAmount;

      private Map<String, Object> extraParams;

      private Map<String, String> metadata;

      private Recurring recurring;

      private TaxBehavior taxBehavior;

      private Long unitAmount;

      private BigDecimal unitAmountDecimal;

      /** Finalize and obtain parameter instance from this builder. */
      public ProductCreateParams.DefaultPriceData build() {
        return new ProductCreateParams.DefaultPriceData(
            this.currency,
            this.currencyOptions,
            this.customUnitAmount,
            this.extraParams,
            this.metadata,
            this.recurring,
            this.taxBehavior,
            this.unitAmount,
            this.unitAmountDecimal);
      }

      /**
       * <strong>Required.</strong> Three-letter <a
       * href="https://www.iso.org/iso-4217-currency-codes.html">ISO currency code</a>, in
       * lowercase. Must be a <a href="https://stripe.com/docs/currencies">supported currency</a>.
       */
      public Builder setCurrency(String currency) {
        this.currency = currency;
        return this;
      }

      /**
       * Add a key/value pair to `currencyOptions` map. A map is initialized for the first
       * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
       * See {@link ProductCreateParams.DefaultPriceData#currencyOptions} for the field
       * documentation.
       */
      public Builder putCurrencyOption(
          String key, ProductCreateParams.DefaultPriceData.CurrencyOption value) {
        if (this.currencyOptions == null) {
          this.currencyOptions = new HashMap<>();
        }
        this.currencyOptions.put(key, value);
        return this;
      }

      /**
       * Add all map key/value pairs to `currencyOptions` map. A map is initialized for the first
       * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
       * See {@link ProductCreateParams.DefaultPriceData#currencyOptions} for the field
       * documentation.
       */
      public Builder putAllCurrencyOption(
          Map<String, ProductCreateParams.DefaultPriceData.CurrencyOption> map) {
        if (this.currencyOptions == null) {
          this.currencyOptions = new HashMap<>();
        }
        this.currencyOptions.putAll(map);
        return this;
      }

      /**
       * When set, provides configuration for the amount to be adjusted by the customer during
       * Checkout Sessions and Payment Links.
       */
      public Builder setCustomUnitAmount(
          ProductCreateParams.DefaultPriceData.CustomUnitAmount customUnitAmount) {
        this.customUnitAmount = customUnitAmount;
        return this;
      }

      /**
       * Add a key/value pair to `extraParams` map. A map is initialized for the first `put/putAll`
       * call, and subsequent calls add additional key/value pairs to the original map. See {@link
       * ProductCreateParams.DefaultPriceData#extraParams} for the field documentation.
       */
      public Builder putExtraParam(String key, Object value) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.put(key, value);
        return this;
      }

      /**
       * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
       * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
       * See {@link ProductCreateParams.DefaultPriceData#extraParams} for the field documentation.
       */
      public Builder putAllExtraParam(Map<String, Object> map) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.putAll(map);
        return this;
      }

      /**
       * Add a key/value pair to `metadata` map. A map is initialized for the first `put/putAll`
       * call, and subsequent calls add additional key/value pairs to the original map. See {@link
       * ProductCreateParams.DefaultPriceData#metadata} for the field documentation.
       */
      public Builder putMetadata(String key, String value) {
        if (this.metadata == null) {
          this.metadata = new HashMap<>();
        }
        this.metadata.put(key, value);
        return this;
      }

      /**
       * Add all map key/value pairs to `metadata` map. A map is initialized for the first
       * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
       * See {@link ProductCreateParams.DefaultPriceData#metadata} for the field documentation.
       */
      public Builder putAllMetadata(Map<String, String> map) {
        if (this.metadata == null) {
          this.metadata = new HashMap<>();
        }
        this.metadata.putAll(map);
        return this;
      }

      /**
       * The recurring components of a price such as {@code interval} and {@code interval_count}.
       */
      public Builder setRecurring(ProductCreateParams.DefaultPriceData.Recurring recurring) {
        this.recurring = recurring;
        return this;
      }

      /**
       * Only required if a <a
       * href="https://stripe.com/docs/tax/products-prices-tax-categories-tax-behavior#setting-a-default-tax-behavior-(recommended)">default
       * tax behavior</a> was not provided in the Stripe Tax settings. Specifies whether the price
       * is considered inclusive of taxes or exclusive of taxes. One of {@code inclusive}, {@code
       * exclusive}, or {@code unspecified}. Once specified as either {@code inclusive} or {@code
       * exclusive}, it cannot be changed.
       */
      public Builder setTaxBehavior(ProductCreateParams.DefaultPriceData.TaxBehavior taxBehavior) {
        this.taxBehavior = taxBehavior;
        return this;
      }

      /**
       * A positive integer in cents (or local equivalent) (or 0 for a free price) representing how
       * much to charge. One of {@code unit_amount}, {@code unit_amount_decimal}, or {@code
       * custom_unit_amount} is required.
       */
      public Builder setUnitAmount(Long unitAmount) {
        this.unitAmount = unitAmount;
        return this;
      }

      /**
       * Same as {@code unit_amount}, but accepts a decimal value in cents (or local equivalent)
       * with at most 12 decimal places. Only one of {@code unit_amount} and {@code
       * unit_amount_decimal} can be set.
       */
      public Builder setUnitAmountDecimal(BigDecimal unitAmountDecimal) {
        this.unitAmountDecimal = unitAmountDecimal;
        return this;
      }
    }

    @Getter
    @EqualsAndHashCode(callSuper = false)
    public static class CurrencyOption {
      /**
       * When set, provides configuration for the amount to be adjusted by the customer during
       * Checkout Sessions and Payment Links.
       */
      @SerializedName("custom_unit_amount")
      CustomUnitAmount customUnitAmount;

      /**
       * Map of extra parameters for custom features not available in this client library. The
       * content in this map is not serialized under this field's {@code @SerializedName} value.
       * Instead, each key/value pair is serialized as if the key is a root-level field (serialized)
       * name in this param object. Effectively, this map is flattened to its parent instance.
       */
      @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
      Map<String, Object> extraParams;

      /**
       * Only required if a <a
       * href="https://stripe.com/docs/tax/products-prices-tax-categories-tax-behavior#setting-a-default-tax-behavior-(recommended)">default
       * tax behavior</a> was not provided in the Stripe Tax settings. Specifies whether the price
       * is considered inclusive of taxes or exclusive of taxes. One of {@code inclusive}, {@code
       * exclusive}, or {@code unspecified}. Once specified as either {@code inclusive} or {@code
       * exclusive}, it cannot be changed.
       */
      @SerializedName("tax_behavior")
      TaxBehavior taxBehavior;

      /**
       * Each element represents a pricing tier. This parameter requires {@code billing_scheme} to
       * be set to {@code tiered}. See also the documentation for {@code billing_scheme}.
       */
      @SerializedName("tiers")
      List<ProductCreateParams.DefaultPriceData.CurrencyOption.Tier> tiers;

      /**
       * A positive integer in cents (or local equivalent) (or 0 for a free price) representing how
       * much to charge.
       */
      @SerializedName("unit_amount")
      Long unitAmount;

      /**
       * Same as {@code unit_amount}, but accepts a decimal value in cents (or local equivalent)
       * with at most 12 decimal places. Only one of {@code unit_amount} and {@code
       * unit_amount_decimal} can be set.
       */
      @SerializedName("unit_amount_decimal")
      BigDecimal unitAmountDecimal;

      private CurrencyOption(
          CustomUnitAmount customUnitAmount,
          Map<String, Object> extraParams,
          TaxBehavior taxBehavior,
          List<ProductCreateParams.DefaultPriceData.CurrencyOption.Tier> tiers,
          Long unitAmount,
          BigDecimal unitAmountDecimal) {
        this.customUnitAmount = customUnitAmount;
        this.extraParams = extraParams;
        this.taxBehavior = taxBehavior;
        this.tiers = tiers;
        this.unitAmount = unitAmount;
        this.unitAmountDecimal = unitAmountDecimal;
      }

      public static Builder builder() {
        return new Builder();
      }

      public static class Builder {
        private CustomUnitAmount customUnitAmount;

        private Map<String, Object> extraParams;

        private TaxBehavior taxBehavior;

        private List<ProductCreateParams.DefaultPriceData.CurrencyOption.Tier> tiers;

        private Long unitAmount;

        private BigDecimal unitAmountDecimal;

        /** Finalize and obtain parameter instance from this builder. */
        public ProductCreateParams.DefaultPriceData.CurrencyOption build() {
          return new ProductCreateParams.DefaultPriceData.CurrencyOption(
              this.customUnitAmount,
              this.extraParams,
              this.taxBehavior,
              this.tiers,
              this.unitAmount,
              this.unitAmountDecimal);
        }

        /**
         * When set, provides configuration for the amount to be adjusted by the customer during
         * Checkout Sessions and Payment Links.
         */
        public Builder setCustomUnitAmount(
            ProductCreateParams.DefaultPriceData.CurrencyOption.CustomUnitAmount customUnitAmount) {
          this.customUnitAmount = customUnitAmount;
          return this;
        }

        /**
         * Add a key/value pair to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link ProductCreateParams.DefaultPriceData.CurrencyOption#extraParams} for the
         * field documentation.
         */
        public Builder putExtraParam(String key, Object value) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.put(key, value);
          return this;
        }

        /**
         * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link ProductCreateParams.DefaultPriceData.CurrencyOption#extraParams} for the
         * field documentation.
         */
        public Builder putAllExtraParam(Map<String, Object> map) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.putAll(map);
          return this;
        }

        /**
         * Only required if a <a
         * href="https://stripe.com/docs/tax/products-prices-tax-categories-tax-behavior#setting-a-default-tax-behavior-(recommended)">default
         * tax behavior</a> was not provided in the Stripe Tax settings. Specifies whether the price
         * is considered inclusive of taxes or exclusive of taxes. One of {@code inclusive}, {@code
         * exclusive}, or {@code unspecified}. Once specified as either {@code inclusive} or {@code
         * exclusive}, it cannot be changed.
         */
        public Builder setTaxBehavior(
            ProductCreateParams.DefaultPriceData.CurrencyOption.TaxBehavior taxBehavior) {
          this.taxBehavior = taxBehavior;
          return this;
        }

        /**
         * Add an element to `tiers` list. A list is initialized for the first `add/addAll` call,
         * and subsequent calls adds additional elements to the original list. See {@link
         * ProductCreateParams.DefaultPriceData.CurrencyOption#tiers} for the field documentation.
         */
        public Builder addTier(ProductCreateParams.DefaultPriceData.CurrencyOption.Tier element) {
          if (this.tiers == null) {
            this.tiers = new ArrayList<>();
          }
          this.tiers.add(element);
          return this;
        }

        /**
         * Add all elements to `tiers` list. A list is initialized for the first `add/addAll` call,
         * and subsequent calls adds additional elements to the original list. See {@link
         * ProductCreateParams.DefaultPriceData.CurrencyOption#tiers} for the field documentation.
         */
        public Builder addAllTier(
            List<ProductCreateParams.DefaultPriceData.CurrencyOption.Tier> elements) {
          if (this.tiers == null) {
            this.tiers = new ArrayList<>();
          }
          this.tiers.addAll(elements);
          return this;
        }

        /**
         * A positive integer in cents (or local equivalent) (or 0 for a free price) representing
         * how much to charge.
         */
        public Builder setUnitAmount(Long unitAmount) {
          this.unitAmount = unitAmount;
          return this;
        }

        /**
         * Same as {@code unit_amount}, but accepts a decimal value in cents (or local equivalent)
         * with at most 12 decimal places. Only one of {@code unit_amount} and {@code
         * unit_amount_decimal} can be set.
         */
        public Builder setUnitAmountDecimal(BigDecimal unitAmountDecimal) {
          this.unitAmountDecimal = unitAmountDecimal;
          return this;
        }
      }

      @Getter
      @EqualsAndHashCode(callSuper = false)
      public static class CustomUnitAmount {
        /**
         * <strong>Required.</strong> Pass in {@code true} to enable {@code custom_unit_amount},
         * otherwise omit {@code custom_unit_amount}.
         */
        @SerializedName("enabled")
        Boolean enabled;

        /**
         * Map of extra parameters for custom features not available in this client library. The
         * content in this map is not serialized under this field's {@code @SerializedName} value.
         * Instead, each key/value pair is serialized as if the key is a root-level field
         * (serialized) name in this param object. Effectively, this map is flattened to its parent
         * instance.
         */
        @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
        Map<String, Object> extraParams;

        /** The maximum unit amount the customer can specify for this item. */
        @SerializedName("maximum")
        Long maximum;

        /**
         * The minimum unit amount the customer can specify for this item. Must be at least the
         * minimum charge amount.
         */
        @SerializedName("minimum")
        Long minimum;

        /** The starting unit amount which can be updated by the customer. */
        @SerializedName("preset")
        Long preset;

        private CustomUnitAmount(
            Boolean enabled,
            Map<String, Object> extraParams,
            Long maximum,
            Long minimum,
            Long preset) {
          this.enabled = enabled;
          this.extraParams = extraParams;
          this.maximum = maximum;
          this.minimum = minimum;
          this.preset = preset;
        }

        public static Builder builder() {
          return new Builder();
        }

        public static class Builder {
          private Boolean enabled;

          private Map<String, Object> extraParams;

          private Long maximum;

          private Long minimum;

          private Long preset;

          /** Finalize and obtain parameter instance from this builder. */
          public ProductCreateParams.DefaultPriceData.CurrencyOption.CustomUnitAmount build() {
            return new ProductCreateParams.DefaultPriceData.CurrencyOption.CustomUnitAmount(
                this.enabled, this.extraParams, this.maximum, this.minimum, this.preset);
          }

          /**
           * <strong>Required.</strong> Pass in {@code true} to enable {@code custom_unit_amount},
           * otherwise omit {@code custom_unit_amount}.
           */
          public Builder setEnabled(Boolean enabled) {
            this.enabled = enabled;
            return this;
          }

          /**
           * Add a key/value pair to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link
           * ProductCreateParams.DefaultPriceData.CurrencyOption.CustomUnitAmount#extraParams} for
           * the field documentation.
           */
          public Builder putExtraParam(String key, Object value) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.put(key, value);
            return this;
          }

          /**
           * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link
           * ProductCreateParams.DefaultPriceData.CurrencyOption.CustomUnitAmount#extraParams} for
           * the field documentation.
           */
          public Builder putAllExtraParam(Map<String, Object> map) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.putAll(map);
            return this;
          }

          /** The maximum unit amount the customer can specify for this item. */
          public Builder setMaximum(Long maximum) {
            this.maximum = maximum;
            return this;
          }

          /**
           * The minimum unit amount the customer can specify for this item. Must be at least the
           * minimum charge amount.
           */
          public Builder setMinimum(Long minimum) {
            this.minimum = minimum;
            return this;
          }

          /** The starting unit amount which can be updated by the customer. */
          public Builder setPreset(Long preset) {
            this.preset = preset;
            return this;
          }
        }
      }

      @Getter
      @EqualsAndHashCode(callSuper = false)
      public static class Tier {
        /**
         * Map of extra parameters for custom features not available in this client library. The
         * content in this map is not serialized under this field's {@code @SerializedName} value.
         * Instead, each key/value pair is serialized as if the key is a root-level field
         * (serialized) name in this param object. Effectively, this map is flattened to its parent
         * instance.
         */
        @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
        Map<String, Object> extraParams;

        /**
         * The flat billing amount for an entire tier, regardless of the number of units in the
         * tier.
         */
        @SerializedName("flat_amount")
        Long flatAmount;

        /**
         * Same as {@code flat_amount}, but accepts a decimal value representing an integer in the
         * minor units of the currency. Only one of {@code flat_amount} and {@code
         * flat_amount_decimal} can be set.
         */
        @SerializedName("flat_amount_decimal")
        BigDecimal flatAmountDecimal;

        /** The per unit billing amount for each individual unit for which this tier applies. */
        @SerializedName("unit_amount")
        Long unitAmount;

        /**
         * Same as {@code unit_amount}, but accepts a decimal value in cents (or local equivalent)
         * with at most 12 decimal places. Only one of {@code unit_amount} and {@code
         * unit_amount_decimal} can be set.
         */
        @SerializedName("unit_amount_decimal")
        BigDecimal unitAmountDecimal;

        /**
         * <strong>Required.</strong> Specifies the upper bound of this tier. The lower bound of a
         * tier is the upper bound of the previous tier adding one. Use {@code inf} to define a
         * fallback tier.
         */
        @SerializedName("up_to")
        Object upTo;

        private Tier(
            Map<String, Object> extraParams,
            Long flatAmount,
            BigDecimal flatAmountDecimal,
            Long unitAmount,
            BigDecimal unitAmountDecimal,
            Object upTo) {
          this.extraParams = extraParams;
          this.flatAmount = flatAmount;
          this.flatAmountDecimal = flatAmountDecimal;
          this.unitAmount = unitAmount;
          this.unitAmountDecimal = unitAmountDecimal;
          this.upTo = upTo;
        }

        public static Builder builder() {
          return new Builder();
        }

        public static class Builder {
          private Map<String, Object> extraParams;

          private Long flatAmount;

          private BigDecimal flatAmountDecimal;

          private Long unitAmount;

          private BigDecimal unitAmountDecimal;

          private Object upTo;

          /** Finalize and obtain parameter instance from this builder. */
          public ProductCreateParams.DefaultPriceData.CurrencyOption.Tier build() {
            return new ProductCreateParams.DefaultPriceData.CurrencyOption.Tier(
                this.extraParams,
                this.flatAmount,
                this.flatAmountDecimal,
                this.unitAmount,
                this.unitAmountDecimal,
                this.upTo);
          }

          /**
           * Add a key/value pair to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link ProductCreateParams.DefaultPriceData.CurrencyOption.Tier#extraParams}
           * for the field documentation.
           */
          public Builder putExtraParam(String key, Object value) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.put(key, value);
            return this;
          }

          /**
           * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link ProductCreateParams.DefaultPriceData.CurrencyOption.Tier#extraParams}
           * for the field documentation.
           */
          public Builder putAllExtraParam(Map<String, Object> map) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.putAll(map);
            return this;
          }

          /**
           * The flat billing amount for an entire tier, regardless of the number of units in the
           * tier.
           */
          public Builder setFlatAmount(Long flatAmount) {
            this.flatAmount = flatAmount;
            return this;
          }

          /**
           * Same as {@code flat_amount}, but accepts a decimal value representing an integer in the
           * minor units of the currency. Only one of {@code flat_amount} and {@code
           * flat_amount_decimal} can be set.
           */
          public Builder setFlatAmountDecimal(BigDecimal flatAmountDecimal) {
            this.flatAmountDecimal = flatAmountDecimal;
            return this;
          }

          /** The per unit billing amount for each individual unit for which this tier applies. */
          public Builder setUnitAmount(Long unitAmount) {
            this.unitAmount = unitAmount;
            return this;
          }

          /**
           * Same as {@code unit_amount}, but accepts a decimal value in cents (or local equivalent)
           * with at most 12 decimal places. Only one of {@code unit_amount} and {@code
           * unit_amount_decimal} can be set.
           */
          public Builder setUnitAmountDecimal(BigDecimal unitAmountDecimal) {
            this.unitAmountDecimal = unitAmountDecimal;
            return this;
          }

          /**
           * <strong>Required.</strong> Specifies the upper bound of this tier. The lower bound of a
           * tier is the upper bound of the previous tier adding one. Use {@code inf} to define a
           * fallback tier.
           */
          public Builder setUpTo(
              ProductCreateParams.DefaultPriceData.CurrencyOption.Tier.UpTo upTo) {
            this.upTo = upTo;
            return this;
          }

          /**
           * <strong>Required.</strong> Specifies the upper bound of this tier. The lower bound of a
           * tier is the upper bound of the previous tier adding one. Use {@code inf} to define a
           * fallback tier.
           */
          public Builder setUpTo(Long upTo) {
            this.upTo = upTo;
            return this;
          }
        }

        public enum UpTo implements ApiRequestParams.EnumParam {
          @SerializedName("inf")
          INF("inf");

          @Getter(onMethod_ = {@Override})
          private final String value;

          UpTo(String value) {
            this.value = value;
          }
        }
      }

      public enum TaxBehavior implements ApiRequestParams.EnumParam {
        @SerializedName("exclusive")
        EXCLUSIVE("exclusive"),

        @SerializedName("inclusive")
        INCLUSIVE("inclusive"),

        @SerializedName("unspecified")
        UNSPECIFIED("unspecified");

        @Getter(onMethod_ = {@Override})
        private final String value;

        TaxBehavior(String value) {
          this.value = value;
        }
      }
    }

    @Getter
    @EqualsAndHashCode(callSuper = false)
    public static class CustomUnitAmount {
      /**
       * <strong>Required.</strong> Pass in {@code true} to enable {@code custom_unit_amount},
       * otherwise omit {@code custom_unit_amount}.
       */
      @SerializedName("enabled")
      Boolean enabled;

      /**
       * Map of extra parameters for custom features not available in this client library. The
       * content in this map is not serialized under this field's {@code @SerializedName} value.
       * Instead, each key/value pair is serialized as if the key is a root-level field (serialized)
       * name in this param object. Effectively, this map is flattened to its parent instance.
       */
      @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
      Map<String, Object> extraParams;

      /** The maximum unit amount the customer can specify for this item. */
      @SerializedName("maximum")
      Long maximum;

      /**
       * The minimum unit amount the customer can specify for this item. Must be at least the
       * minimum charge amount.
       */
      @SerializedName("minimum")
      Long minimum;

      /** The starting unit amount which can be updated by the customer. */
      @SerializedName("preset")
      Long preset;

      private CustomUnitAmount(
          Boolean enabled,
          Map<String, Object> extraParams,
          Long maximum,
          Long minimum,
          Long preset) {
        this.enabled = enabled;
        this.extraParams = extraParams;
        this.maximum = maximum;
        this.minimum = minimum;
        this.preset = preset;
      }

      public static Builder builder() {
        return new Builder();
      }

      public static class Builder {
        private Boolean enabled;

        private Map<String, Object> extraParams;

        private Long maximum;

        private Long minimum;

        private Long preset;

        /** Finalize and obtain parameter instance from this builder. */
        public ProductCreateParams.DefaultPriceData.CustomUnitAmount build() {
          return new ProductCreateParams.DefaultPriceData.CustomUnitAmount(
              this.enabled, this.extraParams, this.maximum, this.minimum, this.preset);
        }

        /**
         * <strong>Required.</strong> Pass in {@code true} to enable {@code custom_unit_amount},
         * otherwise omit {@code custom_unit_amount}.
         */
        public Builder setEnabled(Boolean enabled) {
          this.enabled = enabled;
          return this;
        }

        /**
         * Add a key/value pair to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link ProductCreateParams.DefaultPriceData.CustomUnitAmount#extraParams} for
         * the field documentation.
         */
        public Builder putExtraParam(String key, Object value) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.put(key, value);
          return this;
        }

        /**
         * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link ProductCreateParams.DefaultPriceData.CustomUnitAmount#extraParams} for
         * the field documentation.
         */
        public Builder putAllExtraParam(Map<String, Object> map) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.putAll(map);
          return this;
        }

        /** The maximum unit amount the customer can specify for this item. */
        public Builder setMaximum(Long maximum) {
          this.maximum = maximum;
          return this;
        }

        /**
         * The minimum unit amount the customer can specify for this item. Must be at least the
         * minimum charge amount.
         */
        public Builder setMinimum(Long minimum) {
          this.minimum = minimum;
          return this;
        }

        /** The starting unit amount which can be updated by the customer. */
        public Builder setPreset(Long preset) {
          this.preset = preset;
          return this;
        }
      }
    }

    @Getter
    @EqualsAndHashCode(callSuper = false)
    public static class Recurring {
      /**
       * Map of extra parameters for custom features not available in this client library. The
       * content in this map is not serialized under this field's {@code @SerializedName} value.
       * Instead, each key/value pair is serialized as if the key is a root-level field (serialized)
       * name in this param object. Effectively, this map is flattened to its parent instance.
       */
      @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
      Map<String, Object> extraParams;

      /**
       * <strong>Required.</strong> Specifies billing frequency. Either {@code day}, {@code week},
       * {@code month} or {@code year}.
       */
      @SerializedName("interval")
      Interval interval;

      /**
       * The number of intervals between subscription billings. For example, {@code interval=month}
       * and {@code interval_count=3} bills every 3 months. Maximum of three years interval allowed
       * (3 years, 36 months, or 156 weeks).
       */
      @SerializedName("interval_count")
      Long intervalCount;

      private Recurring(Map<String, Object> extraParams, Interval interval, Long intervalCount) {
        this.extraParams = extraParams;
        this.interval = interval;
        this.intervalCount = intervalCount;
      }

      public static Builder builder() {
        return new Builder();
      }

      public static class Builder {
        private Map<String, Object> extraParams;

        private Interval interval;

        private Long intervalCount;

        /** Finalize and obtain parameter instance from this builder. */
        public ProductCreateParams.DefaultPriceData.Recurring build() {
          return new ProductCreateParams.DefaultPriceData.Recurring(
              this.extraParams, this.interval, this.intervalCount);
        }

        /**
         * Add a key/value pair to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link ProductCreateParams.DefaultPriceData.Recurring#extraParams} for the field
         * documentation.
         */
        public Builder putExtraParam(String key, Object value) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.put(key, value);
          return this;
        }

        /**
         * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link ProductCreateParams.DefaultPriceData.Recurring#extraParams} for the field
         * documentation.
         */
        public Builder putAllExtraParam(Map<String, Object> map) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.putAll(map);
          return this;
        }

        /**
         * <strong>Required.</strong> Specifies billing frequency. Either {@code day}, {@code week},
         * {@code month} or {@code year}.
         */
        public Builder setInterval(
            ProductCreateParams.DefaultPriceData.Recurring.Interval interval) {
          this.interval = interval;
          return this;
        }

        /**
         * The number of intervals between subscription billings. For example, {@code
         * interval=month} and {@code interval_count=3} bills every 3 months. Maximum of three years
         * interval allowed (3 years, 36 months, or 156 weeks).
         */
        public Builder setIntervalCount(Long intervalCount) {
          this.intervalCount = intervalCount;
          return this;
        }
      }

      public enum Interval implements ApiRequestParams.EnumParam {
        @SerializedName("day")
        DAY("day"),

        @SerializedName("month")
        MONTH("month"),

        @SerializedName("week")
        WEEK("week"),

        @SerializedName("year")
        YEAR("year");

        @Getter(onMethod_ = {@Override})
        private final String value;

        Interval(String value) {
          this.value = value;
        }
      }
    }

    public enum TaxBehavior implements ApiRequestParams.EnumParam {
      @SerializedName("exclusive")
      EXCLUSIVE("exclusive"),

      @SerializedName("inclusive")
      INCLUSIVE("inclusive"),

      @SerializedName("unspecified")
      UNSPECIFIED("unspecified");

      @Getter(onMethod_ = {@Override})
      private final String value;

      TaxBehavior(String value) {
        this.value = value;
      }
    }
  }

  @Getter
  @EqualsAndHashCode(callSuper = false)
  public static class MarketingFeature {
    /**
     * Map of extra parameters for custom features not available in this client library. The content
     * in this map is not serialized under this field's {@code @SerializedName} value. Instead, each
     * key/value pair is serialized as if the key is a root-level field (serialized) name in this
     * param object. Effectively, this map is flattened to its parent instance.
     */
    @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
    Map<String, Object> extraParams;

    /** <strong>Required.</strong> The marketing feature name. Up to 80 characters long. */
    @SerializedName("name")
    String name;

    private MarketingFeature(Map<String, Object> extraParams, String name) {
      this.extraParams = extraParams;
      this.name = name;
    }

    public static Builder builder() {
      return new Builder();
    }

    public static class Builder {
      private Map<String, Object> extraParams;

      private String name;

      /** Finalize and obtain parameter instance from this builder. */
      public ProductCreateParams.MarketingFeature build() {
        return new ProductCreateParams.MarketingFeature(this.extraParams, this.name);
      }

      /**
       * Add a key/value pair to `extraParams` map. A map is initialized for the first `put/putAll`
       * call, and subsequent calls add additional key/value pairs to the original map. See {@link
       * ProductCreateParams.MarketingFeature#extraParams} for the field documentation.
       */
      public Builder putExtraParam(String key, Object value) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.put(key, value);
        return this;
      }

      /**
       * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
       * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
       * See {@link ProductCreateParams.MarketingFeature#extraParams} for the field documentation.
       */
      public Builder putAllExtraParam(Map<String, Object> map) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.putAll(map);
        return this;
      }

      /** <strong>Required.</strong> The marketing feature name. Up to 80 characters long. */
      public Builder setName(String name) {
        this.name = name;
        return this;
      }
    }
  }

  @Getter
  @EqualsAndHashCode(callSuper = false)
  public static class PackageDimensions {
    /**
     * Map of extra parameters for custom features not available in this client library. The content
     * in this map is not serialized under this field's {@code @SerializedName} value. Instead, each
     * key/value pair is serialized as if the key is a root-level field (serialized) name in this
     * param object. Effectively, this map is flattened to its parent instance.
     */
    @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
    Map<String, Object> extraParams;

    /** <strong>Required.</strong> Height, in inches. Maximum precision is 2 decimal places. */
    @SerializedName("height")
    BigDecimal height;

    /** <strong>Required.</strong> Length, in inches. Maximum precision is 2 decimal places. */
    @SerializedName("length")
    BigDecimal length;

    /** <strong>Required.</strong> Weight, in ounces. Maximum precision is 2 decimal places. */
    @SerializedName("weight")
    BigDecimal weight;

    /** <strong>Required.</strong> Width, in inches. Maximum precision is 2 decimal places. */
    @SerializedName("width")
    BigDecimal width;

    private PackageDimensions(
        Map<String, Object> extraParams,
        BigDecimal height,
        BigDecimal length,
        BigDecimal weight,
        BigDecimal width) {
      this.extraParams = extraParams;
      this.height = height;
      this.length = length;
      this.weight = weight;
      this.width = width;
    }

    public static Builder builder() {
      return new Builder();
    }

    public static class Builder {
      private Map<String, Object> extraParams;

      private BigDecimal height;

      private BigDecimal length;

      private BigDecimal weight;

      private BigDecimal width;

      /** Finalize and obtain parameter instance from this builder. */
      public ProductCreateParams.PackageDimensions build() {
        return new ProductCreateParams.PackageDimensions(
            this.extraParams, this.height, this.length, this.weight, this.width);
      }

      /**
       * Add a key/value pair to `extraParams` map. A map is initialized for the first `put/putAll`
       * call, and subsequent calls add additional key/value pairs to the original map. See {@link
       * ProductCreateParams.PackageDimensions#extraParams} for the field documentation.
       */
      public Builder putExtraParam(String key, Object value) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.put(key, value);
        return this;
      }

      /**
       * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
       * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
       * See {@link ProductCreateParams.PackageDimensions#extraParams} for the field documentation.
       */
      public Builder putAllExtraParam(Map<String, Object> map) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.putAll(map);
        return this;
      }

      /** <strong>Required.</strong> Height, in inches. Maximum precision is 2 decimal places. */
      public Builder setHeight(BigDecimal height) {
        this.height = height;
        return this;
      }

      /** <strong>Required.</strong> Length, in inches. Maximum precision is 2 decimal places. */
      public Builder setLength(BigDecimal length) {
        this.length = length;
        return this;
      }

      /** <strong>Required.</strong> Weight, in ounces. Maximum precision is 2 decimal places. */
      public Builder setWeight(BigDecimal weight) {
        this.weight = weight;
        return this;
      }

      /** <strong>Required.</strong> Width, in inches. Maximum precision is 2 decimal places. */
      public Builder setWidth(BigDecimal width) {
        this.width = width;
        return this;
      }
    }
  }

  public enum Type implements ApiRequestParams.EnumParam {
    @SerializedName("good")
    GOOD("good"),

    @SerializedName("service")
    SERVICE("service");

    @Getter(onMethod_ = {@Override})
    private final String value;

    Type(String value) {
      this.value = value;
    }
  }
}
